% Clase
\documentclass[11pt,a4paper,spanish,twoside]{report}

% Órdenes auxiliares
\input{inc/includes.tex}

% Encabezado y pie de página
\encabezado

\begin{document}

% Silabación extra
\input{inc/hyphenations.tex}

% Portada
\portada{Sistemas para la colaboración}
{Práctica 2}{Desarrollo de un juego colaborativo}
{Rubén Avisón Melero\\Alicia Serrano Sánchez}{\today}

% Licencia
\licencia{Rubén Avisón Melero, Alicia Serrano Sánchez}

\tableofcontents
\newpage

\listoffigures
\newpage


\chapter{Análisis}

\section{Especificación de requisitos}

\subsection{Requisitos iniciales del sistema}
El objetivo de este trabajo consiste en el desarrollo de una aplicación con
funcionalidad colaborativa distribuida síncrona. La interacción con la
aplicación se hace mediante una interfaz gráfica de usuario. El alumno debe
determinar e implementar las técnicas de \emph{awareness} que se consideren
oportunas. 

\subsection{Análisis de requisitos}
Para la realización de esta práctica se implementará el sudoku. El juego
consistirá en la resolución de un \emph{sudoku} de forma colaborativa. Para
ello, el sistema tendrá soporte para la comunicación, colaboración y
coordinación.   

Para la comunicación, el sistema proporciona un \emph{chat}, dónde los usuarios
que estén jugando puedan comentar las posibles soluciones, conocer al usuario
con el que estén jugando, etc. 

Para la coordinación, el sistema desarrolla el método de adquisición de
turnos. Cada participante en el juego cederá el turno cuando éste se pida,
mostrando la solución que hasta ese momento el otro jugador ha realizado.

Se cuenta con dos usuarios: servidor y cliente. El servidor es el que crea la
partida para poder empezar a jugar. El cliente se unirá a la partida
especificando la dirección ip del servidor.

El usuario \emph{servidor} se conecta al sistema por el puerto 4001 y el
usuario \emph{cliente} se conecta al sistema por el puerto 4002.

\chapter{Diseño}

Para iniciar la aplicación se utiliza la pantalla ``Inicio'' en la cual el
servidor es el que crea la partida. El cliente se conectará a la dirección IP
del servidor para que se lance el juego.

Para empezar a jugar, el servidor tiene que cargar un tablero. Para ello, se
tiene un botón para cargar el tablero dependiendo de la dificultad que se
elija: fácil, medio, difícil. Los tableros se guardan en variables de tipo
\emph{String} y mediante una variable de tipo \emph{Random} se elige
aleatoriamente el tablero a mostrar. Para la dificultades fácil, media y
difícil se ha decidido mostrar 30 números, 20 números y 10 números
respectivamente. 

Para la comunicación, se cuenta con dos áreas de texto. Una área está dirigida
a mostrar la conversación que se mantiene entre el servidor y el cliente. La
otra es para escribir el mensaje que quieres enviar. En
cada mensaje enviado se especifica el nombre del usuario que lo ha
escrito. Cada usuario tiene un color asignado para que la conversación sea más
legible. 

Si un usuario no tiene el turno, no puede modificar el tablero. Sólo puede
pedir turno y esperar a que se lo cedan.

El usuario que tiene el turno puede modificar el tablero, así como pulsar los
botones para que le ayuden a una mejora en la resolución del problema. Podrá
ceder el turno sólo cuando el otro jugador se lo pida. Para ello, el botón
``Dar turno'' sólo aparece cuando el otro jugador pulsa ``Pedir turno''.

\section{Protocolos de comunicación}
La comunicación se establece mediante mensajes especiales. Para ello se utiliza
el objeto \emph{mensajeChat} que corresponde al área de texto para escribir de
la comunicación por Chat. Este objeto se modifica según las necesidades de la
aplicación. Para ello, tenemos los siguientes mensajes especiales:
\begin{itemize}
\item \textbf{uptable}: indica que el tablero tiene que actualizarse.
\item \textbf{daturno}: se activa el botón ``Dar turno''.
\item \textbf{toturno}: se le da el turno al otro jugador habilitando la
  escritura en el tablero y haciendo visible el botón ``Cargar sudoku'' por si
  el jugador quiere cargar un tablero distinto al actual.
\item \textbf{updatos}: actualiza la matriz \emph{datos} de tipo \emph{int}
  para que los dos jugadores tengan la solución correcta.
\end{itemize}

\section{Diagrama de clases}
Un diagrama de clases es un tipo de diagrama estático que describe la
estructura de un sistema mostrando sus clases, atributos y las relaciones
entre ellos. Los diagramas de clases son utilizados durante el proceso de
diseño de los sistemas, donde se crea el diseño conceptual de la información
que se manejará en el sistema, y los componentes que se encargarán del
funcionamiento y la relación entre uno y otro.

Al diseñar una clase se debe pensar en cómo se puede identificar un objeto
real, como una persona, un transporte, un documento o un paquete. Estos 
ejemplos de clases de objetos reales son sobre lo que un sistema se diseña.
Durante el proceso del diseño de las clases se toman las propiedades que
identifican como único al objeto y otras propiedades adicionales como datos
que corresponden al objeto. El diagrama de clases incluye mucha más infor-
mación como la relación entre un objeto y otro, la herencia de propiedades de
otro objeto y conjuntos de operaciones/propiedades que son implementadas
para una interfaz.

El diagrama de clases de esta aplicación se puede observar en la figura
\ref{dcls}.

\imagen{p2.png}{10}{Diagrama de clases del \emph{Sudoku}}{dcls}

\chapter{Implementación}

\section{Manual de usuario}

\subsection{Entrada al juego}
La pantalla principal para entrar al juego consta de dos botones: ``CREAR'' y
``UNIRSE''. 
\begin{itemize}
\item El servidor pulsa el botón ``CREAR'' para iniciar una partida, indicando
  su nombre (figura \ref{iniser}).
\imagen{inicioservidor.jpg}{8}{Inicio de la aplicación para el
  servidor}{iniser} 
\item El cliente pulsa el botón ``UNIRSE'' para entrar en una partida ya
  creada, donde tiene que especificar su nombre y la dirección ip a
  la que conectarse (figura \ref{inicli}). 
\imagen{iniciocliente.jpg}{8}{Inicio de la aplicación para el cliente}{inicli}
\end{itemize}

\subsection{Cargar sudoku}
Una vez que cada jugador está en la pantalla principal del juego, el servidor
es el que, en principio, tiene que cargar el tablero. Para ello, el servidor
pulsa el botón ``Cargar Sudoku''. A continuación, se elige la dificultad del
tablero: fácil, medio o difícil (figura \ref{carga}).
\imagen{cargarsudoku.jpg}{11}{Vista de carga del sudoku}{carga}

En el caso de que se esté jugando y un jugador pulse el botón ``Cargar sudoku''
se genera una ventana de advertencia como la que se muestra en la figura
\ref{aviso}, donde el botón ``Aceptar'' reinicia la aplicación y el botón
``Cancelar'' vuelve a la situación actual del juego.

\imagen{cargarsudokujugando.jpg}{11}{Vista de carga del sudoku jugando}{aviso}

\subsection{Petición de turno}
Cada jugador tendrá visible el botón ``Pedir turno'' o el botón ``Dar turno''
según en qué situación esté (figuras \ref{pideturno} y \ref{daturno}).

La pulsación del botón ``Pedir turno'' pone visible el botón ``Dar turno'' en
el otro jugador. De esta manera se controla cuando se pide el turno.

Cuando se pulsa el botón ``Dar turno'', se pone visible el botón ``Pedir
turno'' del mismo usuario, ya que no se tiene el turno y podrá pedirlo. 

El turno de cada jugador se especifica mediante la etiqueta ``ES TU TURNO''
situada en la parte inferior derecha. 

\imagen{clientechat.jpg}{10}{Botón ``Pedir turno'' habilitado}{pideturno}
\imagen{tepidenturno.jpg}{10}{Botón ``Dar turno'' habilitado}{daturno}

\subsection{Editar el tablero}
Para editar el tablero, se pincha sobre cualquier casilla y se escribe. El
número escrito queda reflejado en el tablero del juego.

\subsection{Chat}
El \emph{chat} consta de dos áreas de texto. Una de ellas se utiliza para
escribir mensajes y enviarlos. En la otra, de mayor tamaño, se muestra la
conversación que mantienen servidor y cliente.

Para escribir un mensaje, se escribe en el área de texto de menor tamaño y se
pulsa ``ENVIAR''. El texto escrito se muestra en el área de texto superior junto
con la identificación del que ha escrito el mensaje, como se puede ver en la
figura \ref{chat}. 
\imagen{servidorchat.jpg}{10}{Chat de la aplicación}{chat}
 
\subsection{Ayuda}
El botón de ``Ayuda'' sirve para mostrar una casilla que no esté rellenada y de
esta manera ayudar a la resolución del sudoku.

\subsection{Resolver}
Para resolver todo el sudoku, se pulsa el botón ``Resolver todo'' y se muestra
todo el tablero rellenado con la solución del mismo (figura \ref{todo}).
\imagen{resolvertodo.jpg}{10}{Botón ``Resolver todo'' pulsado}{todo}

\section{Implementación}

\subsection{Introducción}
Con el objetivo de cumplir los requisitos del sistema se ha utilizado el
lenguaje de programación C\#.

C\# es un lenguaje de programación orientado a objetos desarrollado y
estandarizado por \emph{Microsoft} como parte de su plataforma \emph{.NET}. Su
sintaxis básica deriva de C/C++ y utiliza el modelo de objetos de la plataforma
\emph{.NET} el cual es similar al de \emph{Java} aunque incluye mejoras
derivadas de otros lenguajes. 

El programa utilizado para realizar la interfaz de usuario es \emph{Microsoft
  Visual Studio}. Permite a los desarrolladores crear aplicaciones, sitios y
aplicaciones web, así como servicios web en cualquier entorno que soporte la
plataforma \emph{.NET}.

\subsection{Métodos principales}

\subsubsection{manejadorMSG}
Este método es el que maneja los mensajes para que los jugadores estén
actualizados en cada movimiento. Se le pasa un String que es evaluado para
realizar una de las siguientes acciones:
\begin{itemize}
\item Actualizar el tablero.
\item Activar el botón ``Dar turno''.
\item Dar turno al otro jugador: habilitar el botón ``Cargar sudoku'', por si
  se quiere abandonar el juego actual; habilitar la escritura en el tablero e
  indicar que es su turno.
\item Actualizar Datos, que sirve para cargar la solución del sudoku en la
  variable \emph{datos}.
\item Escribir en el área de texto del chat: color verde si es servidor y color
  azul si es cliente. 
\end{itemize}

\begin{lstlisting}[language=java]
  private void manejadorMSG(String Mensaje)
  {
    String d = Mensaje.Substring(0, 7);
    int lon = Mensaje.Length - 8;
    String s = Mensaje + "\n";
    switch (d)
    {
      case "uptable":
         actualizarTablero(Mensaje.Substring(8, Mensaje.Length - 8));
         break;
      case "daturno":
         ActivarDarTurno();
         break;
      case "toturno":
         TomaBotonTurno();
         break;
      case "updatos":
         ActualizarDatos(Mensaje.Substring(8, Mensaje.Length - 8));
         break;
      default:
         if (soyServidor)
         {
            anadeChat(Mensaje, Color.Green);
         }else
         {
            anadeChat(Mensaje, Color.Blue);
            break;
         }
    }
  }

\end{lstlisting}

\subsubsection{RecibirMensaje}
Hilo que comienza en el momento en el que el cliente entra en la
aplicación. Este método se encarga de estar comprobando en todo momento si se
ha recibido algún mensaje. Para ello, se tiene la variable \emph{str} de tipo
String donde se guarda el mensaje recibido. Con esta variable se llama al
método \emph{metodoHiloPorDelegado}, que se ocupa de llamar al
\emph{ManejadorMSG} para realizar las acciones correspondientes según el
contenido del mensaje.

\begin{lstlisting}[language=java]
public void RecibirMensaje()
{
  for (; ; )
  {
    received = new byte[1024];
    int readBytes = 0;
    try { readBytes = tcp.GetStream().Read(received, 0, received.Length); }
    catch (ObjectDisposedException) { return; }
    if (readBytes == 8)
    {
      StringBuilder shutMessage = new StringBuilder(8);
      for (int count = 0; count < 8; count++)
      {
        char ch = (char)received[count];
        shutMessage = shutMessage.Append(ch);
      }
      string shut = "shutdown";
      string receivedMessage = shutMessage.ToString();
      if (receivedMessage.Equals(shut))
      {
        MessageBox.Show(this, "Desconexion.", "Desconexion",
        MessageBoxButtons.OK, MessageBoxIcon.Information); 
        return;
      }
    }
    StringBuilder str = new StringBuilder(1024);
    for (int count = 0; count < readBytes; count++)
    {
      char ch = (char)received[count];
      str = str.Append(ch);
    }
    metodoHiloPorDelegado(str.ToString());
  }
}
\end{lstlisting}

\subsubsection{EscuchaInfinita}
Es similar al método \emph{RecibirMensaje()}, pero el hilo corresponde al
usuario servidor. Al igual que el cliente, se comprueba si se ha recibido algo,
en cuyo caso se procederá a llamar al método \emph{metodoHiloPorDelegado}.

\begin{lstlisting}[language=java]
private void EscuchaInfinita()
{
  for (; ; )
  {
    Thread.Sleep(100);
    byte[] msg = new Byte[maxNoOfBytes];
    byte count1 = 0x01;
    for (int i = 0; i < msg.Length; i++)
    {
      msg[i] = count1++;
    }
    try
    {
      //Leemos el buffer por si se ha recibido algo
      int readBytes = tcp.GetStream().Read(msg, 0, msg.Length);
      if (readBytes == 8)
      {
        StringBuilder shutMessage = new StringBuilder(8);
        for (int count = 0; count < 8; count++)
        {
          char ch = (char)msg[count];
          //shutMessage = shutMessage.Append(ch);
        }
        string shut = "shutdown";
        string receivedMessage = shutMessage.ToString();
        if (receivedMessage.Equals(shut))
        {
          botonEnviar.Enabled = false;
          return;
        }
      }
      // Sino intentamos recoger el mensaje y ponerlo en panatalla
      StringBuilder str = new StringBuilder(maxNoOfBytes);
      for (int count = 0; count < readBytes; count++)
      {
        char ch = (char)msg[count];
        str = str.Append(ch);
        //str = str.Append("\n");
      }
      metodoHiloPorDelegado(str.ToString());
    }
    catch (IOException)
    {
      return;
    }
  }
}  
\end{lstlisting}

\subsubsection{button1\_Click}
Este método corresponde al botón ``Enviar''. El objeto \emph{mensajeChat} se
modifica para que en el diálogo aparezca de quién procede el mensaje
enviado. Se tiene una matriz \emph{jugadores} que identifican el usuario
servidor y el usuario cliente. De esta manera, se añade a \emph{mensajeChat} y
se llama a \emph{añadeChat} con \emph{mensajeChat} y con el color
correspondiente del tipo de usuario. Por último, se escribe el mensaje en
\emph{tcp} de tipo \emph{TCPCliente} para la comprobación que se realiza en los
métodos antes descritos.
\newpage
\begin{lstlisting}[language=java]
private void button1_Click(object sender, EventArgs e)
{
  if (soyServidor)
  {
    
    if (mensajeChat.Text.Length != 0)
    {
      mensajeChat.Text = jugadores[0] + " : " + mensajeChat.Text + "\n";
      anadeChat(mensajeChat.Text, Color.Blue);
      char[] charArray = mensajeChat.Text.ToCharArray(0, mensajeChat.Text.Length);
      dataToSend = new byte[mensajeChat.Text.Length];
      for (int charCount = 0; charCount < mensajeChat.Text.Length; charCount++)
      {
        dataToSend[charCount] = (byte)charArray[charCount];
      }
    }
    else
    {
      dataToSend = new byte[]{(byte)'e',(byte)'m',(byte)'p',(byte)'t',(byte)'y'};
    }
    tcp.GetStream().Write(dataToSend, 0, dataToSend.Length);
    mensajeChat.Text = "";
  }
  else
  {
    if (this.mensajeChat.Text.Length != 0)
    {
      mensajeChat.Text = jugadores[1] + " : " + mensajeChat.Text + "\n";
      anadeChat(mensajeChat.Text, Color.Green);
      char[] charArray = mensajeChat.Text.ToCharArray(0, mensajeChat.Text.Length);
      dataToSend = new byte[mensajeChat.Text.Length];
      for (int charCount = 0; charCount < mensajeChat.Text.Length; charCount++)
      {
        dataToSend[charCount] = (byte)charArray[charCount];
      }
    }
    else
    {
      dataToSend = new byte[] {(byte)'e',(byte)'m',(byte)'p',(byte)'t',(byte)'y };
    }
    tcp.GetStream().Write(dataToSend, 0, dataToSend.Length);
    mensajeChat.Text = "";
  }
}  
\end{lstlisting}

\subsubsection{botonPedirTurno\_Click}
Se modifica \emph{mensajeChat} con el texto ``daturno'' y al igual que el
método anterior, el mensaje se escribe en \emph{tcp}. Se oculta el botón
``Pedir turno''.

\begin{lstlisting}
private void botonPedirTurno_Click(object sender, EventArgs e)
{
  mensajeChat.Text = "daturno";
  char[] charArray = mensajeChat.Text.ToCharArray(0, mensajeChat.Text.Length);
  dataToSend = new byte[mensajeChat.Text.Length];
  for (int charCount = 0; charCount < mensajeChat.Text.Length; charCount++)
  {
    dataToSend[charCount] = (byte)charArray[charCount];
  }
  tcp.GetStream().Write(dataToSend, 0, dataToSend.Length);
  mensajeChat.Text = "";
  botonPedirTurno.Visible = false;
}
  
\end{lstlisting}

\subsubsection{botonDarTurno\_Click}
Se modifica \emph{mensajeChat} con el texto ``toturno'', se escribe el mensaje
en \emph{tcp} y se deshabilita la escritura en el tablero. Si es la primera vez
que se carga el tablero se envían los datos al otro jugador. A continuación se
actualiza el vector \emph{visitados}, que es la variable que guarda el estado
de tablero; y se envía al otro jugador.

\begin{lstlisting}[language=java]
private void botonDarTurno_Click(object sender, EventArgs e)
{            
  botonDarTurno.Visible = false;
  mensajeChat.Text = "toturno";
  char[] charArray = mensajeChat.Text.ToCharArray(0, mensajeChat.Text.Length);
  dataToSend = new byte[mensajeChat.Text.Length];
  for (int charCount = 0; charCount < mensajeChat.Text.Length; charCount++)
  {
    dataToSend[charCount] = (byte)charArray[charCount];
  }
  tcp.GetStream().Write(dataToSend, 0, dataToSend.Length);
  mensajeChat.Text = "";
  ActDesLabel(true);
  botonPedirTurno.Visible = true;
  cargar.Visible = false;
  label1.Visible = false;
  if (primeraVez)
  {
    enviarDatos();
    primeraVez = false;
  }
  ActualizarVisitados();
  enviarVisitados(visitados);
}  
\end{lstlisting}

\subsection{Dificultades enfrentadas}

\subsubsection{Cargar sudokus}
En un principio intentamos cargar los sudokus desde una base de datos creada en
\emph{Microsoft Access}, pero buscamos información de cómo se hacía y lo que
encontrábamos no nos funcionaba.

En segundo lugar probamos a cargar los sudokus desde un fichero \emph{.txt}
pero teníamos el problema de que no sabíamos como leer línea a línea, o que
cogiera sólo los datos de una línea en concreto, etc.

Finalmente optamos por guardarlos en cadenas y elegir uno de ellos según una
variable de tipo \emph{Random}.

\subsubsection{Modificación de la interfaz a través de otro proceso}
Para establecer la comunicación entre un proceso y otro, tuvimos que crear el
método \emph{metodoHiloPorDelegado} que invoca al método \emph{ManejadorMSG},
que es el que se encarga de establecer la comunicación entre los distintos
procesos. Este método tiene la funcionalidad de actualizar el tablero a la
jugada actual, de pasar los datos de la solución para que los dos jugadores
tengan la opción de pedir ayuda y de resolver el tablero, y también se encarga
de pedir o ceder el turno según el botón que se presione.

\subsubsection{Modificar la interfaz introduciendo una matriz}
La idea era introducir una matriz de tipo \emph{textBox} para hacer más fácil la
parte de rellenar el tablero de juego. Cuando implementamos esa matriz, el
programa \emph{Microsoft Studio} nos daba una excepción indicando que no se
podía modificar la interfaz que era creada por el programa, por lo que tuvimos
que conformarnos con tener 81 texboxs y realizar las operaciones con estos
objetos. 

\subsubsection{Matriz visitados}

Al pasar la matriz \emph{visitados} (matriz que guarda el estado
actual del tablero de juego) al otro proceso, daba problemas con los espacios
en blanco que correspondían a casillas que no habían sido rellenadas. Por lo
tanto, en lugar de los espacios en blanco se tuvo que guardar el símbolo \$
para poder actualizar el método correctamente.

\appendix
\chapter{Carga de trabajo}
\begin{center}
  \begin{tabular}{p{7cm}|c}
    \textbf{Apellidos y Nombre} & \textbf{Porcentaje} \\ \hline \hline
    \emph{Avisón Melero, Rubén}    & 50\% \\
    \hline
     - Interfaz gráfica & \\
     - Módulos principales de sistema & \\
     - Documentación & \\
     \hline
    \emph{Serrano Sánchez, Alicia} & 50\% \\ 
    \hline
     - Interfaz gráfica & \\
     - Arquitectura de la interfaz & \\
     - Documentación & \\
  \end{tabular}
\end{center}

\end{document}
